﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using TMPro;
using UnityEditor;
using UnityEngine;


public class BatchTextReplacer : EditorWindow
{
    private string searchPattern = "";
    private string replaceWith = "";
    private string folderPath = "Assets";
    private bool isSearching = false;
    private bool showMatches = false;
    private Vector2 scrollPosition;
    private List<MatchInfo> matches = new List<MatchInfo>();
    private List<MatchInfo> filteredMatches = new List<MatchInfo>();
    private int contextLines = 3;
    private bool useRegex = false;
    private bool matchCase = false;

    // 二次搜索相关变量
    private string secondarySearchPattern = "";
    private bool isSecondarySearching = false;
    private bool useRegexSecondary = false;
    private bool matchCaseSecondary = false;

    [MenuItem("Miao/Tools/搜索匹配替换脚本")]
    public static void ShowWindow()
    {
        GetWindow<BatchTextReplacer>("Batch Text Replacer");
    }

    private void OnGUI()
    {
        GUILayout.Label("批量替换脚本中的文本", EditorStyles.boldLabel);

        EditorGUILayout.Space();

        // 主要搜索区域
        EditorGUILayout.LabelField("主要搜索", EditorStyles.boldLabel);
        searchPattern = EditorGUILayout.TextField("搜索文本:", searchPattern);
        replaceWith = EditorGUILayout.TextField("替换为:", replaceWith);

        EditorGUILayout.Space();

        EditorGUILayout.BeginHorizontal();
        folderPath = EditorGUILayout.TextField("搜索文件夹:", folderPath);
        if (GUILayout.Button("浏览...", GUILayout.Width(80)))
        {
            string selectedPath = EditorUtility.OpenFolderPanel("选择文件夹", Application.dataPath, "");
            if (!string.IsNullOrEmpty(selectedPath))
            {
                folderPath = "Assets" + selectedPath.Replace(Application.dataPath, "");
            }
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();

        EditorGUILayout.BeginHorizontal();
        useRegex = EditorGUILayout.Toggle("使用正则表达式", useRegex);
        matchCase = EditorGUILayout.Toggle("区分大小写", matchCase);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();

        if (GUILayout.Button("搜索", GUILayout.Height(30)))
        {
            if (string.IsNullOrEmpty(searchPattern))
            {
                EditorUtility.DisplayDialog("错误", "请输入搜索文本", "确定");
                return;
            }

            if (!Directory.Exists(folderPath))
            {
                EditorUtility.DisplayDialog("错误", "指定的文件夹不存在", "确定");
                return;
            }

            SearchMatches();
        }

        EditorGUILayout.Space();

        // 二次搜索区域
        if (showMatches && matches.Count > 0)
        {
            EditorGUILayout.LabelField("二次搜索 (在已找到的结果中筛选)", EditorStyles.boldLabel);

            EditorGUILayout.BeginHorizontal();
            secondarySearchPattern = EditorGUILayout.TextField("二次搜索文本:", secondarySearchPattern);

            if (GUILayout.Button("筛选", GUILayout.Width(60)))
            {
                FilterMatches();
            }

            if (filteredMatches.Count > 0 && GUILayout.Button("重置", GUILayout.Width(60)))
            {
                ResetFilter();
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            useRegexSecondary = EditorGUILayout.Toggle("使用正则表达式", useRegexSecondary);
            matchCaseSecondary = EditorGUILayout.Toggle("区分大小写", matchCaseSecondary);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();

            if (isSecondarySearching)
            {
                EditorGUILayout.LabelField("筛选中...");
            }
            else if (filteredMatches.Count > 0)
            {
                EditorGUILayout.LabelField($"筛选结果: {filteredMatches.Count} / {matches.Count} 项");
            }
        }

        EditorGUILayout.Space();

        if (isSearching)
        {
            EditorGUILayout.LabelField("搜索中...");
            Repaint();
        }
        else if (showMatches)
        {
            List<MatchInfo> displayMatches = filteredMatches.Count > 0 ? filteredMatches : matches;
            EditorGUILayout.LabelField($"找到 {displayMatches.Count} 个匹配项");

            if (displayMatches.Count > 0)
            {
                if (GUILayout.Button("替换所有", GUILayout.Height(30)))
                {
                    if (EditorUtility.DisplayDialog("确认替换",
                        $"确定要替换所有匹配项吗？\n搜索文本: {searchPattern}\n替换为: {replaceWith}",
                        "替换", "取消"))
                    {
                        ReplaceAllMatches(displayMatches);
                    }
                }

                EditorGUILayout.Space();

                scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);

                foreach (var match in displayMatches)
                {
                    DrawMatchItem(match);
                    EditorGUILayout.Space();
                    EditorGUILayout.Space();
                }

                EditorGUILayout.EndScrollView();
            }
        }
    }

    private void DrawMatchItem(MatchInfo match)
    {
        EditorGUILayout.BeginVertical(EditorStyles.helpBox);

        // 文件信息和按钮
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.TextField($"文件: {match.FilePath}", EditorStyles.boldLabel);
        //EditorGUILayout.LabelField($"文件: {match.FilePath}", EditorStyles.boldLabel);
        if (GUILayout.Button("定位", GUILayout.Width(60)))
        {
            // 定位逻辑保持不变
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.LabelField($"行号: {match.LineNumber}");
        EditorGUILayout.Space();

        // 获取匹配行
        var targetLine = match.ContextLines.FirstOrDefault(l => l.LineNumber == match.LineNumber);
        if (targetLine != null)
        {
            // 解析匹配位置（不使用富文本）
            var highlights = new List<(int startIndex, int length, Color color)>();
            ParseHighlights(targetLine.Text, highlights,match);

            // 使用默认样式绘制文本区域
            var textAreaStyle = new GUIStyle(EditorStyles.textArea);
            textAreaStyle.wordWrap = true;

            // 拼接所有行文本
            string allText = string.Join("\n", match.ContextLines.Select(l => l.Text));

            // 获取文本区域的Rect
            Rect textAreaRect = GUILayoutUtility.GetRect(
                EditorGUIUtility.currentViewWidth - 40,
                textAreaStyle.CalcHeight(new GUIContent(allText), EditorGUIUtility.currentViewWidth - 40));

            // 绘制文本区域
            string displayedText = EditorGUI.TextArea(textAreaRect, allText, textAreaStyle);

            // 精确计算高亮位置并绘制
            if (highlights.Any())
            {
                // 计算文本区域内的实际文本显示区域
                Rect contentRect = new Rect(
                    textAreaRect.x + textAreaStyle.padding.left,
                    textAreaRect.y + textAreaStyle.padding.top,
                    textAreaRect.width - textAreaStyle.padding.horizontal,
                    textAreaRect.height - textAreaStyle.padding.vertical);

                // 计算每行文本的高度和位置
                string[] lines = allText.Split('\n');
                float currentY = contentRect.y;

                for (int i = 0; i < lines.Length; i++)
                {
                    string line = lines[i];
                    float lineHeight = textAreaStyle.CalcHeight(new GUIContent(line), contentRect.width);

                    // 如果是目标行，绘制高亮
                    if (i == match.ContextLines.IndexOf(targetLine))
                    {
                        DrawHighlightsOnLine(line, highlights, contentRect.x, currentY, contentRect.width, textAreaStyle);
                    }

                    currentY += lineHeight;
                }
            }
        }

        EditorGUILayout.Space();
        if (GUILayout.Button("替换此项"))
        {
            ReplaceSingleMatch(match);
        }
        EditorGUILayout.EndVertical();
    }

    // 解析匹配位置
    private void ParseHighlights(string text, List<(int startIndex, int length, Color color)> highlights, MatchInfo match)
    {
        // 主要搜索高亮（红色半透明）
        if (!string.IsNullOrEmpty(searchPattern))
        {
            FindMatches(text, searchPattern, useRegex, matchCase, new Color(1f, 0f, 0f, 0.4f), highlights);
        }

        // 二次搜索高亮（黄色半透明）
        if (!string.IsNullOrEmpty(secondarySearchPattern) && filteredMatches.Contains(match))
        {
            FindMatches(text, secondarySearchPattern, useRegexSecondary, matchCaseSecondary, new Color(1f, 1f, 0f, 0.4f), highlights);
        }
    }

    // 查找匹配位置
    private void FindMatches(string text, string pattern, bool useRegex, bool matchCase, Color color, List<(int, int, Color)> highlights)
    {
        if (string.IsNullOrEmpty(pattern)) return;

        if (useRegex)
        {
            RegexOptions options = matchCase ? RegexOptions.None : RegexOptions.IgnoreCase;
            foreach (Match m in Regex.Matches(text, pattern, options))
            {
                highlights.Add((m.Index, m.Length, color));
            }
        }
        else
        {
            StringComparison comparison = matchCase ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
            int index = 0;
            while ((index = text.IndexOf(pattern, index, comparison)) >= 0)
            {
                highlights.Add((index, pattern.Length, color));
                index += pattern.Length;
            }
        }
    }

    // 在指定行上绘制高亮
    private void DrawHighlightsOnLine(string line, List<(int startIndex, int length, Color color)> highlights,
                                     float x, float y, float maxWidth, GUIStyle style)
    {
        foreach (var highlight in highlights)
        {
            // 计算高亮文本的宽度
            string preText = line.Substring(0, highlight.startIndex);
            string highlightText = line.Substring(highlight.startIndex, highlight.length);

            float preWidth = style.CalcSize(new GUIContent(preText)).x;
            float highlightWidth = style.CalcSize(new GUIContent(highlightText)).x;

            // 考虑文本换行
            float lineWidth = style.CalcSize(new GUIContent(line)).x;
            int lineCount = Mathf.CeilToInt(lineWidth / maxWidth);

            for (int i = 0; i < lineCount; i++)
            {
                float lineStart = i * maxWidth;
                float lineEnd = (i + 1) * maxWidth;

                // 计算高亮区域与当前行的交集
                float highlightStart = preWidth;
                float highlightEnd = preWidth + highlightWidth;

                if (highlightEnd > lineStart && highlightStart < lineEnd)
                {
                    float visibleStart = Mathf.Max(highlightStart, lineStart);
                    float visibleEnd = Mathf.Min(highlightEnd, lineEnd);
                    float visibleWidth = visibleEnd - visibleStart;

                    // 计算高亮区域的位置
                    Rect highlightRect = new Rect(
                        x + visibleStart - lineStart,
                        y + i * style.lineHeight,
                        visibleWidth,
                        style.lineHeight);

                    // 绘制高亮色块
                    GUI.DrawTexture(highlightRect, MakeTex(1, 1, highlight.color));
                }
            }
        }
    }

    // 创建单色纹理
    private Texture2D MakeTex(int width, int height, Color col)
    {
        Color[] pix = new Color[width * height];
        for (int i = 0; i < pix.Length; i++)
            pix[i] = col;
        Texture2D result = new Texture2D(width, height);
        result.SetPixels(pix);
        result.Apply();
        return result;
    }

    private void SearchMatches()
    {
        matches.Clear();
        filteredMatches.Clear();
        isSearching = true;
        showMatches = false;
        Repaint();

        // 使用协程进行搜索，避免界面卡顿
        EditorApplication.update += SearchCoroutine;
    }

    private void SearchCoroutine()
    {
        try
        {
            string[] files = Directory.GetFiles(Application.dataPath + folderPath.Substring(6), "*.cs", SearchOption.AllDirectories);

            foreach (string file in files)
            {
                string relativePath = "Assets" + file.Substring(Application.dataPath.Length);
                matches.AddRange(ProcessFile(relativePath));
            }
        }
        catch (Exception e)
        {
            Debug.LogError($"搜索过程中发生错误: {e.Message}");
        }

        isSearching = false;
        showMatches = true;
        EditorApplication.update -= SearchCoroutine;
        Repaint();
    }

    private List<MatchInfo> ProcessFile(string filePath)
    {
        List<MatchInfo> fileMatches = new List<MatchInfo>();
        try
        {
            string[] lines = File.ReadAllLines(filePath);

            for (int i = 0; i < lines.Length; i++)
            {
                bool isMatch = false;
                string line = lines[i];

                if (useRegex)
                {
                    RegexOptions options = matchCase ? RegexOptions.None : RegexOptions.IgnoreCase;
                    isMatch = Regex.IsMatch(line, searchPattern, options);
                }
                else
                {
                    StringComparison comparison = matchCase ?
                        StringComparison.Ordinal :
                        StringComparison.OrdinalIgnoreCase;
                    isMatch = line.IndexOf(searchPattern, comparison) >= 0;
                }

                if (isMatch)
                {
                    List<ContextLine> context = GetContextLines(lines, i, contextLines);
                    fileMatches.Add(new MatchInfo
                    {
                        FilePath = filePath,
                        LineNumber = i + 1,
                        ContextLines = context
                    });
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogError($"处理文件 {filePath} 时发生错误: {e.Message}");
        }
        return fileMatches;
    }

    private List<ContextLine> GetContextLines(string[] lines, int lineIndex, int contextLines)
    {
        List<ContextLine> result = new List<ContextLine>();

        int startLine = Math.Max(0, lineIndex - contextLines);
        int endLine = Math.Min(lines.Length - 1, lineIndex + contextLines);

        for (int i = startLine; i <= endLine; i++)
        {
            result.Add(new ContextLine
            {
                LineNumber = i + 1,
                Text = lines[i]
            });
        }

        return result;
    }

    private void ReplaceSingleMatch(MatchInfo match)
    {
        try
        {
            string[] lines = File.ReadAllLines(match.FilePath);
            int lineIndex = match.LineNumber - 1;

            if (lineIndex >= 0 && lineIndex < lines.Length)
            {
                string originalLine = lines[lineIndex];
                string newLine;

                if (useRegex)
                {
                    RegexOptions options = matchCase ? RegexOptions.None : RegexOptions.IgnoreCase;
                    newLine = Regex.Replace(originalLine, searchPattern, replaceWith, options);
                }
                else
                {
                    newLine = originalLine.Replace(searchPattern, replaceWith,
                        matchCase ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
                }

                lines[lineIndex] = newLine;
                File.WriteAllLines(match.FilePath, lines);
                AssetDatabase.ImportAsset(match.FilePath);

                // 更新匹配信息
                match.ContextLines = GetContextLines(lines, lineIndex, contextLines);

                // 重新应用筛选
                if (!string.IsNullOrEmpty(secondarySearchPattern))
                {
                    FilterMatches();
                }
            }
        }
        catch (Exception e)
        {
            Debug.LogError($"替换匹配项时发生错误: {e.Message}");
        }
    }

    private void ReplaceAllMatches(List<MatchInfo> matchesToReplace)
    {
        try
        {
            var matchesByFile = matchesToReplace.GroupBy(m => m.FilePath);

            foreach (var group in matchesByFile)
            {
                string filePath = group.Key;
                string[] lines = File.ReadAllLines(filePath);
                bool fileModified = false;

                foreach (var match in group.OrderByDescending(m => m.LineNumber))
                {
                    int lineIndex = match.LineNumber - 1;
                    if (lineIndex >= 0 && lineIndex < lines.Length)
                    {
                        string originalLine = lines[lineIndex];
                        string newLine;

                        if (useRegex)
                        {
                            RegexOptions options = matchCase ? RegexOptions.None : RegexOptions.IgnoreCase;
                            newLine = Regex.Replace(originalLine, searchPattern, replaceWith, options);
                        }
                        else
                        {
                            newLine = originalLine.Replace(searchPattern, replaceWith,
                                matchCase ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
                        }

                        lines[lineIndex] = newLine;
                        fileModified = true;
                    }
                }

                if (fileModified)
                {
                    File.WriteAllLines(filePath, lines);
                    AssetDatabase.ImportAsset(filePath);
                }
            }

            // 重新搜索以更新结果
            SearchMatches();
        }
        catch (Exception e)
        {
            Debug.LogError($"替换所有匹配项时发生错误: {e.Message}");
        }
    }

    // 二次搜索相关方法
    private void FilterMatches()
    {
        if (string.IsNullOrEmpty(secondarySearchPattern))
        {
            EditorUtility.DisplayDialog("提示", "请输入二次搜索文本", "确定");
            return;
        }

        filteredMatches.Clear();
        isSecondarySearching = true;
        Repaint();

        EditorApplication.update += FilterCoroutine;
    }

    private void FilterCoroutine()
    {
        try
        {
            foreach (var match in matches)
            {
                bool isMatch = false;

                // 检查上下文行中是否有匹配
                foreach (var line in match.ContextLines)
                {
                    if (useRegexSecondary)
                    {
                        RegexOptions options = matchCaseSecondary ? RegexOptions.None : RegexOptions.IgnoreCase;
                        isMatch = Regex.IsMatch(line.Text, secondarySearchPattern, options);
                    }
                    else
                    {
                        StringComparison comparison = matchCaseSecondary ?
                            StringComparison.Ordinal :
                            StringComparison.OrdinalIgnoreCase;
                        isMatch = line.Text.IndexOf(secondarySearchPattern, comparison) >= 0;
                    }

                    if (isMatch)
                        break;
                }

                if (isMatch)
                    filteredMatches.Add(match);
            }
        }
        catch (Exception e)
        {
            Debug.LogError($"筛选过程中发生错误: {e.Message}");
        }

        isSecondarySearching = false;
        EditorApplication.update -= FilterCoroutine;
        Repaint();
    }

    private void ResetFilter()
    {
        filteredMatches.Clear();
        secondarySearchPattern = "";
        Repaint();
    }
}

public class MatchInfo
{
    public string FilePath;
    public int LineNumber;
    public List<ContextLine> ContextLines;
}

public class ContextLine
{
    public int LineNumber;
    public string Text;
}